<template>
    <el-form ref="formRef" :model="loginForm" :rules="loginRules" size="large">
        <el-form-item prop="username">
            <el-input v-model="loginForm.username" placeholder="用户名：admin / user">
                <template #prefix>
                    <el-icon>
                        <User />
                    </el-icon>
                </template>
            </el-input>
        </el-form-item>
        <el-form-item prop="password">
            <el-input v-model="loginForm.password" type="password" placeholder="密码：123456" show-password
                autocomplete="new-password">
                <template #prefix>
                    <el-icon>
                        <Lock />
                    </el-icon>
                </template>
            </el-input>
        </el-form-item>
    </el-form>
    <div class="login-btn">
        <el-button :icon="CircleClose" round size="large" @click="resetForm"> 重置 </el-button>
        <el-button :icon="UserFilled" round size="large" type="primary" :loading="loading" @click.prevent="handleLogin">
            登录
        </el-button>
    </div>
</template>
  
<script setup lang="ts">
import md5 from "md5";
import { ref, watch, onMounted } from 'vue'
import { useRouter, useRoute } from "vue-router";

import { CircleClose, UserFilled, Lock, User } from "@element-plus/icons-vue";
import type { ElForm, FormInstance } from "element-plus";
import { reqLoginAPI, reqUserInfoAPI } from '@/api/modules/login'
import { useTabsStore } from "@/stores/modules/tabs";
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
import { useUserInfoStore } from "@/stores/modules/userInfo";
import {initDynamicRouter} from '@/routers/index'
const userInfoStore = useUserInfoStore()

// 创建了 ref 对象并与视图中的 el-form 进行了绑定
const formRef = ref()
const redirect = ref('')
const loading = ref(false);

const route = useRoute()
const router = useRouter()
const tabsStore = useTabsStore();
const keepAliveStore = useKeepAliveStore();

//表单数据
const loginForm = ref({
    username: 'admin',
    password: '123456',
})
// 表单验证规则
//#region 
// 验证用户名是否合法
const validateUsername = (_rule: any, value: any, callback: any) => {
    if (value.length < 4) {
        // 验证不通过，抛出一个 Error
        callback(new Error('用户名长度不能小于4位'))
    } else {
        // 验证通过
        callback()
    }
}
// 验证密码是否合法
const validatePassword = (_rule: any, value: any, callback: any) => {
    if (value.length < 6) {
        callback(new Error('密码长度不能小于6位'))
    } else {
        callback()
    }
}
//表单验证规则
const loginRules = {
    // key 要验证的表单的属性
    // 因为每一套规则实际上是由多个规范组成的，这个数组中能填写的配置参考上面的 RuleItem
    username: [{ required: true, validator: validateUsername }],
    // trigger 触发验证的方式为失去焦点时
    password: [{ required: true, trigger: 'blur', validator: validatePassword }],
};
//#endregion

//获取最新路由带回来的重定向地址
watch(route, () => {
    redirect.value = route.query && route.query.redirect as string
}, { immediate: true })

//点击登陆的回调
const handleLogin = async () => {
    // validate : 表单验证,表单格式不通过就不执行后续代码提交表单
    if (!formRef.value) return;
    formRef.value?.validate(async (valid: any) => {
        if (!valid) return;
        loading.value = true;
        try {
            //1. 获取当前用户token并持久化
            const { data: tokenData } = await reqLoginAPI({ ...loginForm.value, password: md5(loginForm.value.password) })
            // 虽然可以直接修改仓库state，但是出于代码结构来说，全局的状态管理还是不要直接在各个组件处随意修改状态，保持单向数据流
            userInfoStore.setToken(tokenData.token)
            //2. 根据token获取用户信息，分开获取，便于维护
            // const { data: userInfoData } = await reqUserInfoAPI()
            // userInfoStore.setToken(userInfoData)
            //3. 初始化用户路由表
            await initDynamicRouter();
            // 清空 tabs、keepAlive 数据
            tabsStore.closeMultipleTab();
            keepAliveStore.setKeepAliveName();
            
            router.push({ path: '/' })
        } finally {
            loading.value = false;
        }
    }
    )
}
// 重置表单
const resetForm = () => {
    formRef.value.resetFields();
};

onMounted(() => {
    // 监听 enter 事件（调用登录）
    document.onkeydown = (e: KeyboardEvent) => {
        e = (window.event as KeyboardEvent) || e;
        if (e.code === "Enter" || e.code === "enter" || e.code === "NumpadEnter") {
            if (loading.value) return;
            handleLogin();
        }
    };
});
</script>
  
<style scoped lang="scss">
@import "../index.scss";
</style>